#include "maininterface.h"
#include "ui_maininterface.h"

mainInterface::mainInterface(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::mainInterface)
{
    ui->setupUi(this);
    keyboardVisible = false;

    this->setWindowFlag(Qt::FramelessWindowHint);           //去边框
    //    this->setAttribute(Qt::WA_TranslucentBackground);       //半透明背景


    //初始化定时器
    dataTimer = new QTimer(this);
    connect(dataTimer, &QTimer::timeout, this, &mainInterface::readFlowData);
    dataTimer->start(1000); // 每秒读取一次

    //更新时间
    clockTimer = new QTimer(this);
    connect(clockTimer, &QTimer::timeout, this, &mainInterface::updateDateTime);
    clockTimer->start(1000); // 每秒更新一次时间

    // 初始化键盘进程
    keyboardProcess = new QProcess(this);
    keyboardVisible = false;



    //初始化Modbus连接
    setupModbusConnection();

    //初始化时间显示
    updateDateTime();

}

mainInterface::~mainInterface()
{
    delete ui;
}

//退出
void mainInterface::on_exitPushButton_clicked()
{
    QMessageBox quitMes;                        //创建退出弹窗对象
    quitMes.setWindowTitle("关闭界面");          //弹窗标题
    quitMes.setWindowIcon(QIcon(":/widdgetMainInterface/exit.png"));        //设置窗口图标
    quitMes.setIcon(QMessageBox::Warning);      //弹窗图片
    quitMes.setText("请确认是否退出");              //弹窗文本

    quitMes.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);      //设置Ok和Cancle两个按钮
    quitMes.setButtonText(QMessageBox::Ok, "确认");           //Ok改为确认
    quitMes.setButtonText(QMessageBox::Cancel,"取消");        //Cancle改为取消

    int result = quitMes.exec();       //显示信息框等待用户交互
    //如果用户选择了Ok
    if(result == QMessageBox::Ok)
    {
        this->close();          //关闭界面
    }
    else    //用户取消什么都不做
    {

    }


    this->close();
}

//设置串口参数
void mainInterface::setupModbusConnection()
{
    modbusDevice = new QModbusRtuSerialMaster(this);

    // 设置Modbus RTU参数
    modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM1");
    modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,QSerialPort::Baud115200);
    modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
    modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
    modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);

    // 连接错误信号
    connect(modbusDevice, &QModbusDevice::errorOccurred, [](QModbusDevice::Error error) {
        qDebug() << "Modbus Error:" << error;
    });

    // 尝试连接设备
    if (!modbusDevice->connectDevice()) {
        qDebug() << "无法连接";
    } else {
        qDebug() << "成功连接";
    }
}


//读取数据
void mainInterface::readFlowData()
{
    if (!modbusDevice || modbusDevice->state() != QModbusDevice::ConnectedState){
        return;
    }
    // 读取流量寄存器 (地址4104-4105, 对应0x1008-0x1009)
    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 4104, 2);
    //    QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, 0, 2);


    if (auto *reply = modbusDevice->sendReadRequest(readUnit, 4)) { // 设备地址4
        if (!reply->isFinished()) {
            connect(reply, &QModbusReply::finished, this, &mainInterface::handleReadResult);
        } else {
            delete reply;
        }
    } else {
        qDebug() << "读取错误: " << modbusDevice->errorString();
    }
}

//更新时间
void mainInterface::updateDateTime()
{
    QDateTime currentTime = QDateTime::currentDateTime();
    QString ymdTimeStr = currentTime.toString("yyyy年MM月dd日");
    QString hmsTimeStr = currentTime.toString("hh:mm:ss");

    ui->currentTimeymdlabel->setText(ymdTimeStr);
    ui->currentTimehmslabel->setText(hmsTimeStr);


}

//大小端排序
//大端模式：高字节在低地址，低字节在高地址
//小端模式：低字节在低地址，高字节在高地址
float mainInterface::convertToFloat(quint16 reg1, quint16 reg2, bool isBigEndian)
{
    union {
        quint32 i;
        float f;
    } converter;

    if (isBigEndian) {
        converter.i = (reg1 << 16) | reg2;
    } else {
        converter.i = (reg2 << 16) | reg1;
    }
    return converter.f;
}

//处理读取数据
void mainInterface::handleReadResult()
{

    auto reply = qobject_cast<QModbusReply *>(sender());
    if (!reply){
        return;
    }

    if (reply->error() == QModbusDevice::NoError) {
        const QModbusDataUnit unit = reply->result();

        // 将数据值转换为字符串
        QString dataStr;
        float flowValuee = 0;
        flowValuee = convertToFloat(unit.value(0),unit.value(1),0);
        // 显示带一位小数的结果
        ui->flowlabel->setText(QString::number(flowValuee, 'f', 1));
    }
    else {
        qDebug() << "读取数据错误" << reply->errorString();
    }

    reply->deleteLater();

}

//高低字节交换
quint16 mainInterface::swapBytes(quint16 value)
{
    return ((value << 8) & 0xFF00) | ((value >> 8) & 0x00FF);

}

//转换数据
float mainInterface::parseFloatFromRegisters(const QVector<quint16> &registers)
{



    // 根据协议文档，每个寄存器内部进行字节交换
    quint16 low = swapBytes(registers[0]);
    quint16 high = swapBytes(registers[1]);

    //组合为32位整数
    //    qint32 combined = (static_cast<quint32>(high)<<16) | low;
    quint32 combined = (qFromBigEndian(high) << 16) | qFromBigEndian(low);

    // 重新解释为浮点数
    float result;
    memcpy(&result, &combined, sizeof(result));

    return result;

}

//软键盘
void mainInterface::on_keyboardPushButton_clicked()
{
    if (!keyboardVisible) {
        bool started = false;

        // 方法1: 使用QProcess尝试启动
        keyboardProcess->start("osk.exe");
        if (keyboardProcess->waitForStarted(1500)) {
            keyboardVisible = true;
            started = true;
            qDebug() << "软键盘已启动 (QProcess)";
        }

        // 方法2: 如果QProcess失败，尝试完整路径
        if (!started) {
            QString oskPath = "C:\\Windows\\System32\\osk.exe";
            keyboardProcess->start(oskPath);
            if (keyboardProcess->waitForStarted(1500)) {
                keyboardVisible = true;
                started = true;
                qDebug() << "软键盘已启动 (完整路径)";
            }
        }

        // 方法3: 如果前两种方法失败，使用Windows API绕过重定向
        if (!started) {
            qDebug() << "尝试使用Windows API启动软键盘";

            // 禁用文件系统重定向
            PVOID oldValue;
            Wow64DisableWow64FsRedirection(&oldValue);

            // 使用ShellExecute启动
            HINSTANCE result = ShellExecuteW(
                        0,
                        L"open",
                        L"osk.exe",
                        0,
                        0,
                        SW_SHOWNORMAL
                        );

            // 恢复文件系统重定向
            Wow64RevertWow64FsRedirection(oldValue);

            if (reinterpret_cast<int>(result) > 32) {
                keyboardVisible = true;
                started = true;
                qDebug() << "软键盘已启动 (Windows API)";
            } else {
                qDebug() << "Windows API启动失败, 错误码:" << reinterpret_cast<int>(result);
            }
        }

        if (!started) {
            QMessageBox::warning(this, "错误", "无法启动软键盘。请确保系统支持屏幕键盘(osk.exe)。");
        }
        else {
            // 关闭软键盘
            if (keyboardProcess->state() == QProcess::Running) {
                keyboardProcess->terminate();
                if (keyboardProcess->waitForFinished(1000)) {
                    keyboardVisible = false;
                    qDebug() << "软键盘已关闭";
                } else {
                    qDebug() << "无法关闭软键盘:" << keyboardProcess->errorString();
                }
            } else {
                keyboardVisible = false;
            }
        }
    }

}

//历史记录
void mainInterface::on_historyPushButton_clicked()
{
    QMessageBox::information(this,"历史记录","查看历史记录");
}

//设置
void mainInterface::on_setPushButton_clicked()
{
    QMessageBox::information(this, "系统设置", "系统设置功能");
}

//帮助
void mainInterface::on_helpPushButton_clicked()
{
    QMessageBox::information(this, "帮助", "流量监控系统帮助文档\n\n"
                                         "1. 系统每秒自动更新流量数据\n"
                                         "2. 点击键盘图标调用系统软键盘\n"
                             );
}
